﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using QuarryPlanner.Domain.Config;
using QuarryPlanner.Domain.DTOs;
using QuarryPlanner.Domain.Entities;
using QuarryPlanner.Domain.Interfaces.Persistence;
using QuarryPlanner.Domain.Services;
using System;
using System.Collections.Generic;

namespace QuarryPlanner.Domain.Test.Services
{
    // Author(s): Ryan Redburn
    // Created: 11/5/2014

    [TestClass]
    public class DailyReportServiceTest
    {
        #region [ QuarryHours ]

        #region [ GetByID ]

        [TestMethod]
        public void GetQHByID_ValidID_ExpectedResult()
        {
            // Arrange
            var quarryHours = new QuarryHoursDTO { QuarryHoursID = 1 };
            var reportRepo = new Mock<IDailyReportRepository>();
            var reportService = new DailyReportService(reportRepo.Object);
            DomainMapConfig.Initialize();
            reportRepo.Setup(x => x.FindQuarryHoursByID(1)).Returns(quarryHours);

            // Act
            var report = reportService.GetQuarryHoursByID(1);

            // Assert
            Assert.AreEqual(1, report.QuarryHoursID);
        }

        [TestMethod]
        public void GetQHByID_IDOutOfRange_ArgumentOutOfRangeException()
        {
            // Arrange
            var assert = false;
            var reportRepo = new Mock<IDailyReportRepository>();
            var reportService = new DailyReportService(reportRepo.Object);

            // Act
            try
            {
                reportService.GetQuarryHoursByID(-2);
            }
            catch (ArgumentOutOfRangeException)
            {
                assert = true;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }

        #endregion

        #region [ GetAll ]

        [TestMethod]
        public void GetAllQH_ExpectedResult()
        {
            // Arrange
            var reports = new List<QuarryHoursDTO> { new QuarryHoursDTO { QuarryHoursID = 1 }, new QuarryHoursDTO { QuarryHoursID = 2 } };
            var reportRepo = new Mock<IDailyReportRepository>();
            var reportService = new DailyReportService(reportRepo.Object);
            DomainMapConfig.Initialize();
            reportRepo.Setup(x => x.FindAllQuarryHours()).Returns(reports);

            // Act
            var result = reportService.GetAllQuarryHours();

            // Assert
            Assert.AreEqual(2, result.Count);
        }

        #endregion

        #region [ Save ]

        [TestMethod]
        public void SaveQH_NullInput_ArgumentNullException()
        {
            // Arrange
            var assert = false;
            QuarryHours quarryHours = null;
            var reportRepo = new Mock<IDailyReportRepository>();
            var reportService = new DailyReportService(reportRepo.Object);
            DomainMapConfig.Initialize();

            // Act
            try
            {
                reportService.Save(quarryHours);
            }
            catch (ArgumentNullException)
            {
                assert = true;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }

        [TestMethod]
        public void SaveQH_ValidInput_NoExceptions()
        {
            // Arrange
            var assert = true;
            var quarryHours = new QuarryHours { AboveGroundHours = 5, BelowGroundHours = 5, NumberOfEmployees = 2, DateAdded = DateTime.Now };
            var reportRepo = new Mock<IDailyReportRepository>();
            var reportService = new DailyReportService(reportRepo.Object);
            DomainMapConfig.Initialize();

            // Act
            try
            {
                reportService.Save(quarryHours);
            }
            catch (Exception)
            {
                assert = false;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }

        #endregion

        #region [ Delete ]

        [TestMethod]
        public void DeleteQH_NullInput_ArgumentNullException()
        {
            // Arrange
            var assert = false;
            QuarryHours quarryHours = null;
            var reportRepo = new Mock<IDailyReportRepository>();
            var reportService = new DailyReportService(reportRepo.Object);
            DomainMapConfig.Initialize();

            // Act
            try
            {
                reportService.Delete(quarryHours);
            }
            catch (ArgumentNullException)
            {
                assert = true;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }

        [TestMethod]
        public void DeleteQH_ValidInput_NoExceptions()
        {
            // Arrange
            var assert = true;
            var quarryHours = new QuarryHours { AboveGroundHours = 5, BelowGroundHours = 5, NumberOfEmployees = 2, DateAdded = DateTime.Now };
            var reportRepo = new Mock<IDailyReportRepository>();
            var reportService = new DailyReportService(reportRepo.Object);
            DomainMapConfig.Initialize();

            // Act
            try
            {
                reportService.Delete(quarryHours);
            }
            catch (Exception)
            {
                assert = false;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }

        #endregion

        #endregion

        #region [ MVE ]

        #region [ GetByID ]

        [TestMethod]
        public void GetMVEByID_ValidID_ExpectedResult()
        {
            // Arrange
            var mve = new MobileVehicleExamDTO { MobileVehicleExamID = 1 };
            var reportRepo = new Mock<IDailyReportRepository>();
            var reportService = new DailyReportService(reportRepo.Object);
            DomainMapConfig.Initialize();
            reportRepo.Setup(x => x.FindMVEByID(1)).Returns(mve);

            // Act
            var report = reportService.GetQuarryHoursByID(1);

            // Assert
            Assert.AreEqual(1, report.QuarryHoursID);
        }

        [TestMethod]
        public void GetMVEByID_IDOutOfRange_ArgumentOutOfRangeException()
        {
            // Arrange
            var assert = false;
            var reportRepo = new Mock<IDailyReportRepository>();
            var reportService = new DailyReportService(reportRepo.Object);

            // Act
            try
            {
                reportService.GetMVEByID(-2);
            }
            catch (ArgumentOutOfRangeException)
            {
                assert = true;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }

        #endregion

        #region [ GetAll ]

        [TestMethod]
        public void GetAllMVE_ExpectedResult()
        {
            // Arrange
            var reports = new List<MobileVehicleExamDTO> { new MobileVehicleExamDTO { MobileVehicleExamID = 1 }, new MobileVehicleExamDTO { MobileVehicleExamID = 2 } };
            var reportRepo = new Mock<IDailyReportRepository>();
            var reportService = new DailyReportService(reportRepo.Object);
            DomainMapConfig.Initialize();
            reportRepo.Setup(x => x.FindAllMVE()).Returns(reports);

            // Act
            var result = reportService.GetAllMVE();

            // Assert
            Assert.AreEqual(2, result.Count);
        }

        #endregion

        #region [ Save ]

        [TestMethod]
        public void SaveMVE_NullInput_ArgumentNullException()
        {
            // Arrange
            var assert = false;
            MobileVehicleExam mve = null;
            var reportRepo = new Mock<IDailyReportRepository>();
            var reportService = new DailyReportService(reportRepo.Object);
            DomainMapConfig.Initialize();

            // Act
            try
            {
                reportService.Save(mve);
            }
            catch (ArgumentNullException)
            {
                assert = true;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }

        [TestMethod]
        public void SaveMVE_ValidInput_NoExceptions()
        {
            // Arrange
            var assert = true;
            var mve = new MobileVehicleExam { International = true, Loader = true, THForkLift = true, TLForkLift = true, Truck = true, DateAdded = DateTime.Now };
            var reportRepo = new Mock<IDailyReportRepository>();
            var reportService = new DailyReportService(reportRepo.Object);
            DomainMapConfig.Initialize();

            // Act
            try
            {
                reportService.Save(mve);
            }
            catch (Exception)
            {
                assert = false;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }

        #endregion

        #region [ Delete ]

        [TestMethod]
        public void DeleteMVE_NullInput_ArgumentNullException()
        {
            // Arrange
            var assert = false;
            MobileVehicleExam mve = null;
            var reportRepo = new Mock<IDailyReportRepository>();
            var reportService = new DailyReportService(reportRepo.Object);
            DomainMapConfig.Initialize();

            // Act
            try
            {
                reportService.Delete(mve);
            }
            catch (ArgumentNullException)
            {
                assert = true;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }

        [TestMethod]
        public void DeleteMVE_ValidInput_NoExceptions()
        {
            // Arrange
            var assert = true;
            var mve = new MobileVehicleExam { International = true, Loader = true, THForkLift = true, TLForkLift = true, Truck = true, DateAdded = DateTime.Now };
            var reportRepo = new Mock<IDailyReportRepository>();
            var reportService = new DailyReportService(reportRepo.Object);
            DomainMapConfig.Initialize();

            // Act
            try
            {
                reportService.Delete(mve);
            }
            catch (Exception)
            {
                assert = false;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }

        #endregion

        #endregion

        #region [ WPE ]

        #region [ GetByID ]

        [TestMethod]
        public void GetWPEByID_ValidID_ExpectedResult()
        {
            // Arrange
            var wpe = new WorkPlaceExamDTO { WorkPlaceExamID = 1 };
            var reportRepo = new Mock<IDailyReportRepository>();
            var reportService = new DailyReportService(reportRepo.Object);
            DomainMapConfig.Initialize();
            reportRepo.Setup(x => x.FindWPEByID(1)).Returns(wpe);

            // Act
            var report = reportService.GetQuarryHoursByID(1);

            // Assert
            Assert.AreEqual(1, report.QuarryHoursID);
        }

        [TestMethod]
        public void GetWPEByID_IDOutOfRange_ArgumentOutOfRangeException()
        {
            // Arrange
            var assert = false;
            var reportRepo = new Mock<IDailyReportRepository>();
            var reportService = new DailyReportService(reportRepo.Object);

            // Act
            try
            {
                reportService.GetWPEByID(-2);
            }
            catch (ArgumentOutOfRangeException)
            {
                assert = true;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }

        #endregion

        #region [ GetAll ]

        [TestMethod]
        public void GetAllWPE_ExpectedResult()
        {
            // Arrange
            var reports = new List<WorkPlaceExamDTO> { new WorkPlaceExamDTO { WorkPlaceExamID = 1 }, new WorkPlaceExamDTO { WorkPlaceExamID = 2 } };
            var reportRepo = new Mock<IDailyReportRepository>();
            var reportService = new DailyReportService(reportRepo.Object);
            DomainMapConfig.Initialize();
            reportRepo.Setup(x => x.FindAllWPE()).Returns(reports);

            // Act
            var result = reportService.GetAllWPE();

            // Assert
            Assert.AreEqual(2, result.Count);
        }

        #endregion

        #region [ Save ]

        [TestMethod]
        public void SaveWPE_NullInput_ArgumentNullException()
        {
            // Arrange
            var assert = false;
            WorkPlaceExam wpe = null;
            var reportRepo = new Mock<IDailyReportRepository>();
            var reportService = new DailyReportService(reportRepo.Object);
            DomainMapConfig.Initialize();

            // Act
            try
            {
                reportService.Save(wpe);
            }
            catch (ArgumentNullException)
            {
                assert = true;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }

        [TestMethod]
        public void SaveWPE_ValidInput_NoExceptions()
        {
            // Arrange
            var assert = true;
            var wpe = new WorkPlaceExam { FiveFootSaw = true, Guillotine=true, Polisher = true, SevenFootSaw = true, Surfacer = true, WaterJet = true, DateAdded = DateTime.Now };
            var reportRepo = new Mock<IDailyReportRepository>();
            var reportService = new DailyReportService(reportRepo.Object);
            DomainMapConfig.Initialize();

            // Act
            try
            {
                reportService.Save(wpe);
            }
            catch (Exception)
            {
                assert = false;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }

        #endregion

        #region [ Delete ]

        [TestMethod]
        public void DeleteWPE_NullInput_ArgumentNullException()
        {
            // Arrange
            var assert = false;
            WorkPlaceExam wpe = null;
            var reportRepo = new Mock<IDailyReportRepository>();
            var reportService = new DailyReportService(reportRepo.Object);
            DomainMapConfig.Initialize();

            // Act
            try
            {
                reportService.Delete(wpe);
            }
            catch (ArgumentNullException)
            {
                assert = true;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }

        [TestMethod]
        public void DeleteWPE_ValidInput_NoExceptions()
        {
            // Arrange
            var assert = true;
            var wpe = new WorkPlaceExam { FiveFootSaw = true, Guillotine = true, Polisher = true, SevenFootSaw = true, Surfacer = true, WaterJet = true, DateAdded = DateTime.Now };
            var reportRepo = new Mock<IDailyReportRepository>();
            var reportService = new DailyReportService(reportRepo.Object);
            DomainMapConfig.Initialize();

            // Act
            try
            {
                reportService.Delete(wpe);
            }
            catch (Exception)
            {
                assert = false;
            }
            finally
            {
                // Assert
                Assert.IsTrue(assert);
            }
        }

        #endregion

        #endregion
    }
}
